package com.netty.netty.low.demo4;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NettyServer {

  private static Logger log= LoggerFactory.getLogger(NettyServer.class);

  public static void main(String[] args) {


      new ServerBootstrap()
              .group(new NioEventLoopGroup(),new NioEventLoopGroup(2))
              .channel(NioServerSocketChannel.class)
              .childHandler(new ChannelInitializer<SocketChannel>() {

                  //pipeline结构
                  //head->handle1->handle2->handle3->handle4->handle5->handle6->tail
                  //且为‘双向链表’，触发Inbound事件则会从head->tail一直走Inbound方法。
                  //触发Outbound事件则会从tail->head一直走Outbound方法。只有触发了对应事件才会走对应的方法。。。。。。
                  @Override
                  protected void initChannel(SocketChannel socketChannel) throws Exception {

                      socketChannel.pipeline().addLast(new StringDecoder());

                      //Inbound处理器
                      //为处理器取名字
                      socketChannel.pipeline().addLast("handle1",new ChannelInboundHandlerAdapter(){

                          @Override
                          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                              log.warn(Thread.currentThread().getName()+"==>"+"handle1");
                              super.channelRead(ctx, msg); //向下传递
                          }
                      });

                      socketChannel.pipeline().addLast("handle2",new ChannelInboundHandlerAdapter(){
                          @Override
                          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                              log.warn(msg.toString());
                              log.warn(Thread.currentThread().getName()+"==>"+"handle2");
                              super.channelRead(ctx, msg); //向下传递
                          }
                      });

                      socketChannel.pipeline().addLast("handle3",new ChannelInboundHandlerAdapter(){
                          @Override
                          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

                              //***不能用这种方法，client会收不到
//                              ByteBuffer buffer = StandardCharsets.UTF_8.encode("hello world");


                              //***用这种,记住*****一定要指定字符类型UTF-8***
                              ByteBuf byteBuf = ctx.alloc().buffer().writeBytes("hello".getBytes("utf-8"));
                              //发送数据，触发OutBound事件
                              socketChannel.writeAndFlush(byteBuf);

                              log.warn(Thread.currentThread().getName()+"==>"+"handle3");
                              super.channelRead(ctx, msg); //向下传递
                          }
                      });

                      //Outbound处理器
                      socketChannel.pipeline().addLast("handle4",new ChannelOutboundHandlerAdapter(){

                          @Override
                          public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                              log.warn(Thread.currentThread().getName()+"==>"+"handle4");
                              super.write(ctx, msg, promise);
                          }
                      });

                      socketChannel.pipeline().addLast("handle5",new ChannelOutboundHandlerAdapter(){

                          @Override
                          public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                              log.warn(Thread.currentThread().getName()+"==>"+"handle5");
                              super.write(ctx, msg, promise);
                          }
                      });

                      socketChannel.pipeline().addLast("handle6",new ChannelOutboundHandlerAdapter(){

                          @Override
                          public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                              log.warn(Thread.currentThread().getName()+"==>"+"handle6");
                              super.write(ctx, msg, promise);
                          }
                      });
                  }
              }).bind(8080);



  }
}
